//可以正常运行c文件

#include <stdio.h>
#include <stdlib.h>
//#include <stdbool.h>
#include <string.h>

// 定义常量
#define MIN_YEAR 1900
#define MAX_YEAR 2100

// 农历数据结构
typedef struct {
    int leapMonth;      // 闰月月份（0表示无闰月）
    int monthDays[14];  // 各月天数（索引0不使用，1-12为正常月份，13为闰月）
} LunarYear;

// 农历日期结构
typedef struct {
    int lunarYear;      // 农历年
    int lunarMonth;     // 农历月（负数表示闰月）
    int lunarDay;       // 农历日
    char ganzhiYear[10];// 天干地支年
    char lunarMonthName[10]; // 农历月名称
    char lunarDayName[10];   // 农历日名称
} LunarDate;

// 农历月份名称
const char* lunarMonthNames[] = { "正月", "二月", "三月", "四月", "五月", "六月","七月", "八月", "九月", "十月", "冬月", "腊月" };

// 农历日期名称
const char* lunarDayNames[] = { "初一", "初二", "初三", "初四", "初五", "初六", "初七", "初八", "初九", "初十",
                             "十一", "十二", "十三", "十四", "十五", "十六", "十七", "十八", "十九", "二十",
                             "廿一", "廿二", "廿三", "廿四", "廿五", "廿六", "廿七", "廿八", "廿九", "三十" };

// 天干地支
const char* tianGan[] = { "甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸" };
const char* diZhi[] = { "子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥" };

// 重新整理的农历数据（1900-2100年）
// 数据格式：高4位=闰月月份，低12位=各月天数（0=29天，1=30天）
const unsigned int lunarData[] = {
    0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, //1900-1909
    0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977, //1910-1919
    0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, //1920-1929
    0x06566, 0x0d4a0, 0x0ea50, 0x16a95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950, //1930-1939
    0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, //1940-1949
    0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5b0, 0x14573, 0x052b0, 0x0a9a8, 0x0e950, 0x06aa0, //1950-1959
    0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, //1960-1969
    0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b6a0, 0x195a6, //1970-1979
    0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570, //1980-1989
    0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x05ac0, 0x0ab60, 0x096d5, 0x092e0, //1990-1999
    0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5, //2000-2009
    0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, //2010-2019
    0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530, //2020-2029
    0x05aa0, 0x076a3, 0x096d0, 0x04afb, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, //2030-2039
    0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0, //2040-2049
    0x14b63, 0x09370, 0x049f8, 0x04970, 0x064b0, 0x168a6, 0x0ea50, 0x06aa0, 0x1a6c4, 0x0aae0, //2050-2059
    0x092e0, 0x0d2e3, 0x0c960, 0x0d557, 0x0d4a0, 0x0da50, 0x05d55, 0x056a0, 0x0a6d0, 0x055d4, //2060-2069
    0x052d0, 0x0a9b8, 0x0a950, 0x0b4a0, 0x0b6a6, 0x0ad50, 0x055a0, 0x0aba4, 0x0a5b0, 0x052b0, //2070-2079
    0x0b273, 0x06930, 0x07337, 0x06aa0, 0x0ad50, 0x14b55, 0x04b60, 0x0a570, 0x054e4, 0x0d160, //2080-2089
    0x0e968, 0x0d520, 0x0daa0, 0x16aa6, 0x056d0, 0x04ae0, 0x0a9d4, 0x0a2d0, 0x0d150, 0x0f252, //2090-2099
    0x0d520

};

// 判断是否为闰年
int isLeapYear(int year) {
    return ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) ? 1 : 0;
}

// 获取指定月份的天数
int daysInMonth(int year, int month) {
    static const int days[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
    if (month == 2 && isLeapYear(year))
        return 29;
    return days[month];
}

// 计算从1900年1月31日到指定日期的天数
int daysFromBase(int year, int month, int day) {
    int days = 0;
    for (int y = 1900; y < year; y++) {
        days += isLeapYear(y) ? 366 : 365;
    }
    for (int m = 1; m < month; m++) {
        days += daysInMonth(year, m);
    }
    days += day;
    days -= 30;
    return days;
}

// 解析农历数据
LunarYear parseLunarYear(int year) {
    LunarYear result = { 0 };
    if (year < MIN_YEAR || year > MAX_YEAR) {
        return result;
    }

    int index = year - MIN_YEAR;
    unsigned int data = lunarData[index];

    // 解析闰月
    result.leapMonth = (data) & (unsigned long long)0xF;

    // 解析各月天数
    for (int i = 1; i <= 12; i++) {
        result.monthDays[i] = ((data >> (16 - i)) & (unsigned long long)0x1) ? 30 : 29;
    }

    // 如果有闰月，设置闰月天数
    // 注意：这里使用高4位的最后一位作为闰月天数标志
    if (result.leapMonth > 0) {
        result.monthDays[13] = ((data >> 16) & (unsigned long long)0x1) ? 30 : 29;
    }

    return result;
}

// 公历转农历
LunarDate gregorianToLunar(int year, int month, int day) {
    LunarDate result = { 0,0,0,"","","" };

    printf("\n===== 公历转农历开始 =====\n");
    printf("输入公历日期: %d年%d月%d日\n", year, month, day);

    // 验证日期有效性
    if (year < MIN_YEAR || year > MAX_YEAR) {
        printf("错误: 年份超出范围 (1900-2100)\n");
        strcpy(result.ganzhiYear, "未知");
        strcpy(result.lunarMonthName, "未知");
        strcpy(result.lunarDayName, "未知");
        return result;
    }

    // 计算天干地支年
    int tgIndex = (year - 4) % 10;
    int dzIndex = (year - 4) % 12;
    if (tgIndex < 0) tgIndex += 10;
    if (dzIndex < 0) dzIndex += 12;
    sprintf(result.ganzhiYear, "%s%s", tianGan[tgIndex], diZhi[dzIndex]);
    //printf("天干地支年计算: %s年\n", result.ganzhiYear);

    // 计算从1900年1月31日到指定日期的天数
    int days = daysFromBase(year, month, day);
    //printf("距离1900年1月31日的天数: %d\n", days);

    // 查找农历年份
    int lunarYear = 1900;
    int daysInYear = 0;

    printf("\n开始查找农历年份...\n");
    while (1) {
        LunarYear currentYear = parseLunarYear(lunarYear);
        daysInYear = 0;

        // 计算该农历年的总天数
        for (int i = 1; i <= 12; i++) {
            daysInYear += currentYear.monthDays[i];
        }

        // 如果有闰月，加上闰月天数
        if (currentYear.leapMonth > 0) {
            daysInYear += currentYear.monthDays[13];
        }

        printf("农历年 %d: 总天数=%d, 闰月=%d\n", lunarYear, daysInYear, currentYear.leapMonth);

        if (days <= daysInYear) {
            printf("找到匹配年份: %d年, 剩余天数=%d\n", lunarYear, days);
            break;
        }

        days -= daysInYear;
        lunarYear++;
        printf("天数递减后剩余: %d, 进入下一年\n", days);
    }

    result.lunarYear = lunarYear;

    // 计算农历月和日
    int lunarMonth = 1;
    int isLeap = 0;

    printf("\n开始计算农历月和日...\n");
    printf("当前农历年数据: 闰月=%d\n", parseLunarYear(lunarYear).leapMonth);

    // 计算农历月份和日期
    LunarYear currentYear = parseLunarYear(lunarYear);

    while (days > 0) {
        int daysInMonth = currentYear.monthDays[lunarMonth];
        printf("\n当前处理月份: %d月, 天数=%d, 剩余天数=%d, 闰月标志=%d\n", lunarMonth, daysInMonth, days, isLeap);

        if (days <= daysInMonth) {
            printf("找到匹配: 农历月=%d, 农历日=%d\n", isLeap ? -lunarMonth : lunarMonth, days);

            result.lunarMonth = isLeap ? -lunarMonth : lunarMonth;
            result.lunarDay = days;

            break;
        }

        // 处理闰月
        if (lunarMonth == currentYear.leapMonth) {
            printf("检测到闰月: 当前月份=%d, 闰月标志=%d\n", lunarMonth, isLeap);

            if (!isLeap) {
                printf("进入闰月处理, 减去当月天数\n");
                isLeap = 0;

                days -= daysInMonth;
                printf("处理闰月后剩余天数: %d\n", days);

                continue;
            }
            else {
                printf("处理闰月天数, 设置为: %d\n", currentYear.monthDays[13]);
                daysInMonth = currentYear.monthDays[13];  // 闰月天数

                isLeap = 0;
                printf("重置闰月标志为false\n");
            }
        }

        days -= daysInMonth;
        lunarMonth++;
        printf("减去当月天数后剩余: %d, 月份递增为: %d\n", days, lunarMonth);

        // 如果月份超过12，退出循环
        if (lunarMonth > 12) {
            printf("警告: 月份超过12, 退出循环\n");
            break;
        }
    }

    // 设置农历月名称
    printf("\n设置农历月名称...\n");
    if (result.lunarMonth != 0 && abs(result.lunarMonth) >= 1 && abs(result.lunarMonth) <= 12) {
        strcpy(result.lunarMonthName, lunarMonthNames[abs(result.lunarMonth) - 1]);
        printf("基础月名称: %s\n", result.lunarMonthName);

        if (result.lunarMonth < 0) {
            char temp[20];
            sprintf(temp, "闰%s", result.lunarMonthName);
            strcpy(result.lunarMonthName, temp);
            printf("添加闰字后: %s\n", result.lunarMonthName);
        }
    }
    else {
        printf("错误: 农历月超出范围\n");
        strcpy(result.lunarMonthName, "未知");
    }

    // 设置农历日名称
    printf("设置农历日名称...\n");
    if (result.lunarDay >= 1 && result.lunarDay <= 30) {
        strcpy(result.lunarDayName, lunarDayNames[result.lunarDay - 1]);
        printf("农历日名称: %s\n", result.lunarDayName);
    }
    else {
        printf("错误: 农历日超出范围\n");
        strcpy(result.lunarDayName, "未知");
    }

    printf("\n===== 转换结果 =====\n");
    printf("农历日期: %s年 %s %s\n",
        result.ganzhiYear, result.lunarMonthName, result.lunarDayName);
    printf("====================\n\n");

    return result;
}

// 主函数
int main() {
    int year, month, day;


    printf("公历转农历程序 (1900-2100)\n");
    printf("请输入公历日期（年 月 日）: ");

    year = 2025, month = 5, day = 10;
    // 转换为农历
    LunarDate lunarDate = gregorianToLunar(year, month, day);

    // 输出结果
    printf("\n公历: %d年%d月%d日\n", year, month, day);
    printf("农历: %s年 %s %s\n", lunarDate.ganzhiYear, lunarDate.lunarMonthName, lunarDate.lunarDayName);

    return 0;
}